package perl.compiler;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import perl.lexical.classes.*;

public class SemantycAnalizer {
	
	private Map<Integer, Token> tokens;
	private Map<String, VariableElement> variableElements;
	private Map<String, FunctionElement> functionElements;
	private List<String> variableList;
	private List<String> functionList;
	final TokenClassEnum SCALAR = TokenClassEnum.SCALAR_IDENT;
	final TokenClassEnum ARRAY = TokenClassEnum.ARRAY_IDENT;
	final TokenClassEnum IDENT = TokenClassEnum.IDENTIFIER;
	final Token SUB = new Token(TokenClassEnum.KEYWORD, Keyword.SUB);
	
	public SemantycAnalizer(Map<Integer, Token> tokens) {
		this.tokens = tokens;
	}
	
	public void analize() throws Exception{		
		if(tokens == null){
			throw new Exception("ERORR: There are no tokens to analize");
		}
		variableList = new ArrayList<String>();
		functionList = new ArrayList<String>();
		variableElements = new HashMap<String, VariableElement>();
		functionElements = new HashMap<String, FunctionElement>();
		for(Entry<Integer, Token> token : tokens.entrySet()){
			//System.out.println(token.getValue().isDeclarated());
			if ((token.getValue().getTokenClass() == SCALAR) || (token.getValue().getTokenClass() == ARRAY)){
				String variableName = token.getValue().getLexem();
				if(token.getValue().isDeclarated()){
					VariableElement ve = new VariableElement(); 
					ve.setName(token.getValue().getLexem());
					ve.setType(token.getValue().getTokenClass().toString());
					ve.setNestingLevel(token.getValue().getNestingLevel());
					variableElements.put(ve.getName(), ve);
				}else if(!variableElements.containsKey(variableName)){
					throw new Exception("Error: "+ token.getValue().getLexem() + " was not declarated");
					//System.out.println("ERROOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOR" + token);
				}
					
			} 
			
			if(token.getValue().equals(SUB)){
				FunctionElement fe = new FunctionElement();
				Token funcToken = tokens.get(token.getKey() + 1);
				fe.setName(funcToken.getLexem());
				fe.setNumberOfParameters(0);
				functionElements.put(fe.getName(), fe);
			}
			
			if(token.getValue().getTokenClass() == TokenClassEnum.IDENTIFIER){
				boolean result = false;
				for(Entry<Integer, Token> tokenSub : tokens.entrySet()){
					int key = tokenSub.getKey();
					if(tokenSub.getValue().equals(SUB) && (tokens.get(key+1).getLexem()).equals(token.getValue().getLexem())){
						result = true;
					}
				}
				if(!result){
					throw new Exception("Error in function call: " + token);
				//	System.out.println("Error in function call" + token);
				}
			}
		}
		
		for(Entry<String, VariableElement> ve : variableElements.entrySet()){
			//variableList.add(ve.getValue());
			//System.out.println(ve.getValue());
		}
		
		for(Entry<String, FunctionElement> fe : functionElements.entrySet()){
			System.out.println(fe.getValue());
		}
	}

	public Map<String, VariableElement> getVariableElements() {
		return variableElements;
	}

	public Map<String, FunctionElement> getFunctionElements() {
		return functionElements;
	}



}
